home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Info-Mac 4
/
Info_Mac IV CD-ROM (Pacific HiTech Inc.)(August 1994).iso
/
Development
/
General
/
DR1.#1 PowerPlant ƒ
/
LPrintout.cp
< prev
next >
Wrap
Text File
|
1994-02-10
|
12KB
|
445 lines
// ===========================================================================
// LPrintout.cp ©1993 Metrowerks Inc. All rights reserved.
// ===========================================================================
//
// A View for printing
//
// A Printout object is top level container of a view hierarchy that is
// being printed. It deals with the Mac Print Manager and coordinates
// its subpanes during the printing process.
//
// To print, you must create a Printout object in which you install all
// the Panes that you want to print. Usually, your Printout has the
// dimensions of the paper size (as displayed in the Page Setup dialog).
// Then, the location of a Pane in the Printout is the same as the location
// on the Paper where the Pane will print.
//
// To print a Pane that is inside a Window, you should use a LPlaceHolder
// view in the Printout to specify the size and location of the Pane when
// it prints. You then install the Pane inside the PlaceHolder. When
// printing completes, the PlaceHolder returns the Pane to its original
// place in the Window.
//
// +++ Still under light construction
#include "LPrintout.h"
#include "UPrinting.h"
#include "LListIterator.h"
#include "LStream.h"
#include "LCommander.h"
#include "UReanimator.h"
#include <GestaltEqu.h>
// ---------------------------------------------------------------------------
// • CreatePrintout [static]
// ---------------------------------------------------------------------------
// Return a new Printout object (and its SubPanes) from the data in
// a 'PObj' resource
LPrintout*
LPrintout::CreatePrintout(
ResIDT inPrintoutID)
{
LCommander::SetDefaultCommander(nil);
LPrintout *thePrintout =
(LPrintout*) UReanimator::ReadObjects('PObj', inPrintoutID);
thePrintout->FinishCreate();
return thePrintout;
}
// ---------------------------------------------------------------------------
// • CreatePrintoutStream [static]
// ---------------------------------------------------------------------------
// Return a new Printout object initialized using data from a Stream
LPrintout*
LPrintout::CreatePrintoutStream(
LStream *inStream)
{
DataIDT dataID;
inStream->ReadData(&dataID, sizeof(DataIDT));
SignalIf_(dataID != 'PrtO');
return (new LPrintout(inStream));
}
// ---------------------------------------------------------------------------
// • LPrintout
// ---------------------------------------------------------------------------
// Default Constructor
LPrintout::LPrintout()
{
InitPrintout();
}
// ---------------------------------------------------------------------------
// • LPrintout(THPrint)
// ---------------------------------------------------------------------------
// Construct a Printout from an existing PrintRecord
LPrintout::LPrintout(
THPrint inPrintRecordH)
{
InitPrintout();
SetPrintRecord(inPrintRecordH);
}
// ---------------------------------------------------------------------------
// • LPrintout
// ---------------------------------------------------------------------------
// Construct a Printout from the data in a Stream
LPrintout::LPrintout(
LStream *inStream)
{
InitPrintout();
inStream->ReadData(&mAttributes, sizeof(Uint32));
SetDefaultView(this);
}
// ---------------------------------------------------------------------------
// • InitPrintout
// ---------------------------------------------------------------------------
// Initialize data members to default values
void
LPrintout::InitPrintout()
{
mAttributes = 0;
mPrinterPort = nil;
mHorizPanelCount = 1;
mVertPanelCount = 1;
SetPrintRecord(UPrinting::GetDefaultPrintRecord());
// Create an empty, invisible window
// for installing Toolbox Controls
Rect bounds = {0, 0, 0, 0};
Int32 qdVersion;
OSErr err = Gestalt(gestaltQuickdrawVersion, &qdVersion);
if ( (err != noErr) || (qdVersion == gestaltOriginalQD) ) {
mWindowPort = NewWindow(nil, &bounds, "\p", false, documentProc,
nil, false, 0);
} else {
mWindowPort = NewCWindow(nil, &bounds, "\p", false, documentProc,
nil, false, 0);
}
SetPort(mWindowPort);
OutOfFocus(nil);
SuperActivate(); // A Printout is active and visible
SuperShow();
}
// ---------------------------------------------------------------------------
// • ~LPrintout
// ---------------------------------------------------------------------------
// Destructor
LPrintout::~LPrintout()
{
DeleteAllSubPanes();
if (mWindowPort != nil) {
DisposeWindow(mWindowPort);
}
}
THPrint
LPrintout::GetPrintRecord()
{
return mPrintRecordH;
}
// ---------------------------------------------------------------------------
// • SetPrintRecord
// ---------------------------------------------------------------------------
// Set the Toolbox PrintRecord for a Printout
void
LPrintout::SetPrintRecord(
THPrint inPrintRecordH)
{
mPrintRecordH = inPrintRecordH;
UPrinting::ValidatePrintRecord(inPrintRecordH);
// Size and coordinates system of a Printout depend on the Page
// and Paper rectangles of the PrintRecord. The Print Manager sets
// the port rectangle of the Printer Port to the Page rectangle.
//
// The Page rectangle is usually smaller than the Paper rectangle
// since most printers have mechanical limitations which prevent
// them from printing to the very edge of the paper.
//
// For Printouts, it seems more natural to have (0,0) be the top left
// of the Paper rectangle, so that coordinates are the absolute
// location on the paper. This simplifies setting margins and
// otherwise placing Panes for printing.
Rect paperRect = (**inPrintRecordH).rPaper;
// Printout Frame and Image match the Paper Rectangle
ResizeFrameTo(paperRect.right - paperRect.left,
paperRect.bottom - paperRect.top, false);
ResizeImageTo(paperRect.right - paperRect.left,
paperRect.bottom - paperRect.top, false);
MoveBy(paperRect.left, paperRect.top, false);
}
// ---------------------------------------------------------------------------
// • HasAttribute
// ---------------------------------------------------------------------------
// Return whether a Printout has the specified attribute
Boolean
LPrintout::HasAttribute(
EPrintAttr inAttribute)
{
return ((mAttributes & inAttribute) != 0);
}
void
LPrintout::DoPrintJob()
{
PanelSpec firstPanel;
PanelSpec lastPanel;
Uint16 copyCount;
GetPrintJobSpecs(firstPanel, lastPanel, copyCount);
PrintPanelRange(firstPanel, lastPanel, copyCount);
}
void
LPrintout::PrintPanelRange(
const PanelSpec &inFirstPanel,
const PanelSpec &inLastPanel,
Uint16 inCopyCount)
{
if (UPrinting::OpenPrinter()) {
// +++ Show print status dialog
PrintCopiesOfPages(inFirstPanel, inLastPanel, inCopyCount);
}
Int16 printError = PrError();
UPrinting::ClosePrinter();
if (printError) {
// +++ Post error message
}
// +++ Remove print status dialog
}
// ---------------------------------------------------------------------------
// • CountPanels
// ---------------------------------------------------------------------------
// Count the number of Panels in a Printout
void
LPrintout::CountPanels(
Uint32 &outHorizPanels,
Uint32 &outVertPanels)
{
// The number of Panels in a Printout is the maximum number
// (both horizonal and vertical) of Panels in its SubPanes
Uint32 maxHorizPanels = 1;
Uint32 maxVertPanels = 1;
LListIterator iterator(GetSubPanes(), iterate_FromStart);
LPane *subPane;
while (iterator.Next(subPane)) {
Uint32 subHorizPanels;
Uint32 subVertPanels;
subPane->CountPanels(subHorizPanels, subVertPanels);
if (subHorizPanels > maxHorizPanels) {
maxHorizPanels = subHorizPanels;
}
if (subVertPanels > maxVertPanels) {
maxVertPanels = subVertPanels;
}
}
// Save counts in member variables
// and set output parameters
mHorizPanelCount = outHorizPanels = maxHorizPanels;
mVertPanelCount = outVertPanels = maxVertPanels;
}
// ---------------------------------------------------------------------------
// • PageToPanel
// ---------------------------------------------------------------------------
// Fill in PanelSpec for a given page number
void
LPrintout::PageToPanel(
Uint32 inPageNumber,
PanelSpec &outPanel)
{
outPanel.pageNumber = inPageNumber;
Boolean numberDown = true; // +++ Make a Printout attribute
if (numberDown) {
outPanel.horizIndex = ((inPageNumber - 1) / mVertPanelCount) + 1;
outPanel.vertIndex = ((inPageNumber - 1) % mVertPanelCount) + 1;
} else {
outPanel.horizIndex = ((inPageNumber - 1) % mHorizPanelCount) + 1;
outPanel.vertIndex = ((inPageNumber - 1) / mHorizPanelCount) + 1;
}
}
void
LPrintout::GetPrintJobSpecs(
PanelSpec &outFirstPanel,
PanelSpec &outLastPanel,
Uint16 &outCopyCount)
{
THPrint printRecordH = GetPrintRecord();
// Get info from PrintRecord
Int16 firstPage = (**printRecordH).prJob.iFstPage;
Int16 lastPage = (**printRecordH).prJob.iLstPage;
outCopyCount = (**printRecordH).prJob.iCopies;
// The Print Manager doesn't care about our page numbers. It
// counts the number of calls to PrOpenPage. So setting the
// page range to 1 to 9999 will print all pages that we draw.
(**printRecordH).prJob.iFstPage = 1;
(**printRecordH).prJob.iLstPage = 9999;
// Enforce bounds on page range. Last page can't be greater
// than number of pages in Printout, and first page can't
// be greater than the last page.
Uint32 horizPanelCount;
Uint32 vertPanelCount;
CountPanels(horizPanelCount, vertPanelCount);
Uint32 pageCount = horizPanelCount * vertPanelCount;
if (lastPage > pageCount) {
lastPage = pageCount;
}
if (firstPage > lastPage) {
firstPage = lastPage;
}
PageToPanel(firstPage, outFirstPanel);
PageToPanel(lastPage, outLastPanel);
}
void
LPrintout::PrintCopiesOfPages(
const PanelSpec &inFirstPanel,
const PanelSpec &inLastPanel,
Uint16 inCopyCount)
{
THPrint printRecordH = GetPrintRecord();
Int16 printMgrResFile = CurResFile();
for (Uint16 copy = 1; copy <= inCopyCount; copy++) {
// +++ Install pIdle proc
UseResFile(printMgrResFile);
mPrinterPort = ::PrOpenDoc(printRecordH, nil , nil);
OutOfFocus(nil); // Printer is the current port
PanelSpec thePanel = inFirstPanel;
while (thePanel.pageNumber <= inLastPanel.pageNumber &&
PrError() == noErr) {
::PrOpenPage(mPrinterPort, nil);
if (PrError() == noErr) {
PrintPanel(thePanel, nil);
}
:: PrClosePage(mPrinterPort);
PageToPanel(++thePanel.pageNumber, thePanel);
}
::PrCloseDoc(mPrinterPort);
mPrinterPort = nil;
}
OutOfFocus(nil); // Printer port is gone
if (((**printRecordH).prJob.bJDocLoop == bSpoolLoop) && (PrError() == noErr)) {
TPrStatus printStatus;
::PrPicFile(printRecordH, nil, nil, nil, &printStatus);
}
}
void
LPrintout::PrintPanel(
const PanelSpec &inPanel,
RgnHandle inSuperPrintRgnH)
{
FocusDraw();
PrintPanelSelf(inPanel); // Print this Printout
// Print SubPanes
LListIterator iterator(GetSubPanes(), iterate_FromStart);
LPane *subPane;
while (iterator.Next(subPane)) {
subPane->PrintPanel(inPanel, inSuperPrintRgnH);
}
}
// ---------------------------------------------------------------------------
// • GetMacPort
// ---------------------------------------------------------------------------
// Return the GrafPort associated with a Printout
GrafPtr
LPrintout::GetMacPort() const
{
return (GrafPtr) mPrinterPort;
}
// ---------------------------------------------------------------------------
// • EstablishPort
// ---------------------------------------------------------------------------
// Make Printout the current Port
void
LPrintout::EstablishPort()
{
// A Printer Port only exists during the print loop. At other
// times, we have to use the window port.
GrafPtr printoutPort = (GrafPtr) mPrinterPort;
if (mPrinterPort == nil) {
printoutPort = mWindowPort;
}
SetPort(printoutPort);
}